package com.tonyodev.fetch2.database;

import ohos.utils.net.Uri;

import com.tonyodev.fetch2.Download;
import com.tonyodev.fetch2.EnqueueAction;
import com.tonyodev.fetch2.Error;
import com.tonyodev.fetch2.NetworkType;
import com.tonyodev.fetch2.Priority;
import com.tonyodev.fetch2.Request;
import com.tonyodev.fetch2.Status;
import com.tonyodev.fetch2.util.Defaults;
import com.tonyodev.fetch2.util.TypeConverterExtensions;
import com.tonyodev.fetch2core.Extras;
import com.tonyodev.fetch2core.FetchCoreUtils;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

import static com.tonyodev.fetch2.util.Defaults.DEFAULT_AUTO_RETRY_ATTEMPTS;
import static com.tonyodev.fetch2.util.Defaults.DEFAULT_DOWNLOAD_ON_ENQUEUE;
import static com.tonyodev.fetch2.util.Defaults.DEFAULT_UNIQUE_IDENTIFIER;
import static com.tonyodev.fetch2core.FetchCoreUtils.calculateProgress;

/**
 * @since 2021-05-21
 */
public class DownloadInfo implements Download {


    private int id = 0;
    private String namespace = "";
    private String url = "";
    private String file = "";
    private int group = 0;
    private Priority priority = Defaults.getDefaultPriority();
    private Map<String, String> headers = new HashMap<>();
    private long downloaded = 0L;
    private long total = 1L;
    private Status status = Defaults.getDefaultStatus();
    private Error error = Defaults.getDefaultNoError();
    private NetworkType networkType = Defaults.getDefaultNetworkType();
    private long created = Calendar.getInstance().getTimeInMillis();
    private String tag;
    private EnqueueAction enqueueAction = EnqueueAction.REPLACE_EXISTING;
    private long identifier = DEFAULT_UNIQUE_IDENTIFIER;
    private boolean downloadOnEnqueue = DEFAULT_DOWNLOAD_ON_ENQUEUE;
    private Extras extras = Extras.getEmptyExtras();
    private int autoRetryMaxAttempts = DEFAULT_AUTO_RETRY_ATTEMPTS;
    private int autoRetryAttempts = DEFAULT_AUTO_RETRY_ATTEMPTS;
    private long etaInMilliSeconds = -1L;
    private long downloadedBytesPerSecond = -1L;
    private Request request;

    @Override
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @NotNull
    @Override
    public String getNamespace() {
        return namespace;
    }

    public void setNamespace(String namespace) {
        this.namespace = namespace;
    }

    @NotNull
    @Override
    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    @NotNull
    @Override
    public String getFile() {
        return file;
    }

    public void setFile(String file) {
        this.file = file;
    }

    @Override
    public int getGroup() {
        return group;
    }

    public void setGroup(int group) {
        this.group = group;
    }

    @NotNull
    @Override
    public Priority getPriority() {
        return priority;
    }

    public void setPriority(Priority priority) {
        this.priority = priority;
    }

    @NotNull
    @Override
    public Map<String, String> getHeaders() {
        return headers;
    }

    public void setHeaders(Map<String, String> headers) {
        this.headers = headers;
    }

    @Override
    public long getDownloaded() {
        return downloaded;
    }

    public void setDownloaded(long downloaded) {
        this.downloaded = downloaded;
    }

    @Override
    public long getTotal() {
        return total;
    }

    public void setTotal(long total) {
        this.total = total;
    }

    @NotNull
    @Override
    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    @NotNull
    @Override
    public Error getError() {
        return error;
    }

    public void setError(Error error) {
        this.error = error;
    }

    @NotNull
    @Override
    public NetworkType getNetworkType() {
        return networkType;
    }

    public void setNetworkType(NetworkType networkType) {
        this.networkType = networkType;
    }

    @Override
    public long getCreated() {
        return created;
    }

    public void setCreated(long created) {
        this.created = created;
    }

    @Nullable
    @Override
    public String getTag() {
        return tag;
    }

    public void setTag(String tag) {
        this.tag = tag;
    }

    @Override
    public EnqueueAction getEnqueueAction() {
        return enqueueAction;
    }

    public void setEnqueueAction(EnqueueAction enqueueAction) {
        this.enqueueAction = enqueueAction;
    }

    @Override
    public long getIdentifier() {
        return identifier;
    }

    @Override
    public boolean getDownloadOnEnqueue() {
        return downloadOnEnqueue;
    }

    public void setIdentifier(long identifier) {
        this.identifier = identifier;
    }

    public boolean isDownloadOnEnqueue() {
        return downloadOnEnqueue;
    }

    public void setDownloadOnEnqueue(boolean downloadOnEnqueue) {
        this.downloadOnEnqueue = downloadOnEnqueue;
    }

    @Override
    public Extras getExtras() {
        return extras;
    }

    public void setExtras(Extras extras) {
        this.extras = extras;
    }

    @Override
    public int getAutoRetryMaxAttempts() {
        return autoRetryMaxAttempts;
    }

    public void setAutoRetryMaxAttempts(int autoRetryMaxAttempts) {
        this.autoRetryMaxAttempts = autoRetryMaxAttempts;
    }

    @Override
    public int getAutoRetryAttempts() {
        return autoRetryAttempts;
    }

    public void setAutoRetryAttempts(int autoRetryAttempts) {
        this.autoRetryAttempts = autoRetryAttempts;
    }

    @Override
    public long getEtaInMilliSeconds() {
        return etaInMilliSeconds;
    }

    public void setEtaInMilliSeconds(long etaInMilliSeconds) {
        this.etaInMilliSeconds = etaInMilliSeconds;
    }

    @Override
    public long getDownloadedBytesPerSecond() {
        return downloadedBytesPerSecond;
    }

    public void setDownloadedBytesPerSecond(long downloadedBytesPerSecond) {
        this.downloadedBytesPerSecond = downloadedBytesPerSecond;
    }

    @Override
    public int getProgress() {
        return calculateProgress(downloaded, total);
    }

    @Override
    public Uri getFileUri() {
        return FetchCoreUtils.getFileUri(file);
    }

    @Override
    public Request getRequest() {
        Request request = new Request(url, file);
        request.setGroupId(group);
        request.getHeaders().putAll(headers);
        request.setNetworkType(networkType);
        request.setPriority(priority);
        request.setEnqueueAction(enqueueAction);
        request.setIdentifier(identifier);
        request.setDownloadOnEnqueue(downloadOnEnqueue);
        request.setExtras(extras);
        request.setAutoRetryMaxAttempts(autoRetryMaxAttempts);
        return request;
    }

    @Override
    public Download copy() {
        return TypeConverterExtensions.toDownloadInfo(this,new DownloadInfo());
    }

    public void setRequest(Request request) {
        this.request = request;
    }


    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (this.getClass() != obj.getClass()) return false;
        DownloadInfo other = (DownloadInfo) obj;
        if (id != other.getId()) return false;
        if (namespace != other.getNamespace()) return false;
        if (url != other.getUrl()) return false;
        if (file != other.getFile()) return false;
        if (group != other.getGroup()) return false;
        if (priority != other.getPriority()) return false;
        if (headers != other.getHeaders()) return false;
        if (downloaded != other.getDownloaded()) return false;
        if (total != other.getTotal()) return false;
        if (status != other.getStatus()) return false;
        if (error != other.getError()) return false;
        if (networkType != other.getNetworkType()) return false;
        if (created != other.getCreated()) return false;
        if (tag != other.getTag()) return false;
        if (enqueueAction != other.getEnqueueAction()) return false;
        if (identifier != other.getIdentifier()) return false;
        if (downloadOnEnqueue != other.getDownloadOnEnqueue()) return false;
        if (extras != other.getExtras()) return false;
        if (etaInMilliSeconds != other.getEtaInMilliSeconds()) return false;
        if (downloadedBytesPerSecond != other.getDownloadedBytesPerSecond()) return false;
        if (autoRetryMaxAttempts != other.getAutoRetryMaxAttempts()) return false;
        if (autoRetryAttempts != other.getAutoRetryAttempts()) return false;
        return true;
    }

    @Override
    public int hashCode() {
        int result = id;
        result = 31 * result + namespace.hashCode();
        result = 31 * result + url.hashCode();
        result = 31 * result + file.hashCode();
        result = 31 * result + group;
        result = 31 * result + priority.hashCode();
        result = 31 * result + headers.hashCode();
        result = 31 * result + ((Long) downloaded).hashCode();
        result = 31 * result + ((Long) total).hashCode();
        result = 31 * result + status.hashCode();
        result = 31 * result + error.hashCode();
        result = 31 * result + networkType.hashCode();
        result = 31 * result + ((Long) created).hashCode();
        result = 31 * result + (tag != null ? tag.hashCode() : 0);
        result = 31 * result + enqueueAction.hashCode();
        result = 31 * result + ((Long) identifier).hashCode();
        result = 31 * result + ((Boolean) downloadOnEnqueue).hashCode();
        result = 31 * result + extras.hashCode();
        result = 31 * result + ((Long) etaInMilliSeconds).hashCode();
        result = 31 * result + ((Long) downloadedBytesPerSecond).hashCode();
        result = 31 * result + ((Integer) autoRetryMaxAttempts).hashCode();
        result = 31 * result + ((Integer) autoRetryAttempts).hashCode();
        return result;
    }

    public int describeContents(){
        return 0;
    }

    @Override
    public String toString() {
        return "DownloadInfo{" +
            "id=" + id +
            ", namespace='" + namespace + '\'' +
            ", url='" + url + '\'' +
            ", file='" + file + '\'' +
            ", group=" + group +
            ", priority=" + priority +
            ", headers=" + headers +
            ", downloaded=" + downloaded +
            ", total=" + total +
            ", status=" + status +
            ", error=" + error +
            ", networkType=" + networkType +
            ", created=" + created +
            ", tag='" + tag + '\'' +
            ", enqueueAction=" + enqueueAction +
            ", identifier=" + identifier +
            ", downloadOnEnqueue=" + downloadOnEnqueue +
            ", extras=" + extras +
            ", autoRetryMaxAttempts=" + autoRetryMaxAttempts +
            ", autoRetryAttempts=" + autoRetryAttempts +
            ", etaInMilliSeconds=" + etaInMilliSeconds +
            ", downloadedBytesPerSecond=" + downloadedBytesPerSecond +
            ", request=" + request +
            '}';
    }


}
